iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0

昨天我已經成功新增了「喜愛(愛心)」按鈕,點擊之後愛心會從空心 ♡ 變成實心 ♥,再點一次又會切回空心。這樣的互動效果已經不錯了,但仍然有一個問題:只要跳出頁面或重新整理,所有紀錄就會消失,愛心狀態會全部回到空心。
對於一個音樂專輯網站來說,這樣的體驗並不理想,因為使用者希望自己「喜愛」的歌曲能夠被記錄下來,甚至下次再打開網站時依然存在。今天的目標就是要解決這個問題。


目標:

  • 愛心狀態可以存入瀏覽器。
  • 關閉或重新整理頁面也能保留。

album.js

// 1. 定義 localStorage 的 key,並讀取已喜愛的歌曲
const likedSongsKey = "likedSongs";
let likedSongs = JSON.parse(localStorage.getItem(likedSongsKey)) || [];


// 2. 取得網址參數 id
const urlParams = new URLSearchParams(window.location.search);
const id = urlParams.get("id");


// 3. 如果有對應的專輯就顯示
if (albums[id]) {
    const album = albums[id];
    document.getElementById("album-title").textContent = album.title;
    document.getElementById("album-cover").src = album.cover;
    document.getElementById("album-year").textContent = "Released:" + album.year;


    const songList = document.getElementById("album-songs");
    songList.innerHTML = ""; // 先清空列表


    // 4. 顯示每首歌
    album.songs.forEach((song, index) => {
        const li = document.createElement("li");


        if (typeof song === "string") {
            li.textContent = `${index + 1}. ${song}`;
        } else {
            // 判斷這首歌是否已經被喜愛
            const isLiked = likedSongs.includes(song.name);


            li.innerHTML = `
                <div class="song-item">
                    <span>${index + 1}. <a href="${song.url}" target="_blank">${song.name}</a></span>
                    <div class="action-btns">
                        <a href="lyrics.html?song=${album.title}-${song.name}" class="lyrics-btn">lyrics</a>
                        <button class="like-btn ${isLiked ? "liked" : ""}" data-song-name="${song.name}">
                            ${isLiked ? "♥" : "♡"}
                        </button>
                    </div>
                </div>
            `;
        }


        songList.appendChild(li);
    });


    // 5. 隨機播放按鈕
    const randomBtn = document.getElementById("random-play-btn");
    randomBtn.addEventListener("click", () => {
        const randomSong = album.songs[Math.floor(Math.random() * album.songs.length)];
        const url = typeof randomSong === "string" ? "#" : randomSong.url;
        if (url !== "#") window.open(url, "_blank");
        else alert("這首歌沒有連結可以播放!");
    });


    // 6. 喜愛按鈕事件監聽
    document.querySelectorAll(".like-btn").forEach(btn => {
        btn.addEventListener("click", () => {
            const songName = btn.dataset.songName;
            likedSongs = JSON.parse(localStorage.getItem(likedSongsKey)) || [];


            if (btn.textContent === "♡") {
                // 點擊變紅心,加入 localStorage
                btn.textContent = "♥";
                btn.classList.add("liked");
                if (!likedSongs.includes(songName)) likedSongs.push(songName);
            } else {
                // 再點一次變空心,從 localStorage 移除
                btn.textContent = "♡";
                btn.classList.remove("liked");
                likedSongs = likedSongs.filter(name => name !== songName);
            }


            localStorage.setItem(likedSongsKey, JSON.stringify(likedSongs));
        });
    });
}

步驟解析

  1. localStorage

    • 使用一個 key:likedSongs 來儲存所有被喜愛的歌曲名稱。
    • 這個資料會存在瀏覽器裡,就算關掉分頁或電腦重開機,也不會消失。
  2. 讀取 URL 參數

    • 利用 URLSearchParams 取得專輯 id,確定要渲染哪一張專輯的歌曲清單。
  3. 顯示專輯資訊

    • 把專輯名稱、封面、發行年份等資料動態填入頁面。
  4. 建立歌曲清單

    • 使用迴圈遍歷歌曲資料,生成 <li> 元素。
    • 檢查這首歌是否在 likedSongs 陣列裡,如果有就直接顯示成實心愛心 ♥。
  5. 隨機播放按鈕

    • 使用亂數隨機選一首歌,並在新分頁打開歌曲連結。
  6. 愛心按鈕點擊事件

    • 點擊空心 → 變成紅色實心並加入 localStorage。
    • 點擊實心 → 變回空心,並從 localStorage 移除。
    • 每次點擊後,立即更新 localStorage 內容。

心得

這次最大的收穫是學會了如何利用 localStorage 來保存使用者狀態。其實這個技巧非常常見,不只是在音樂網站,像是購物車、瀏覽紀錄、偏好設定都會用到。
原本只是單純的按鈕切換效果,但加上 localStorage 之後,整個功能變得「有記憶」,就像網站真的認得我一樣。對使用者來說,體驗直接提升了一個層級。
下一篇文會再詳細解釋什麼是 localStorage


上一篇
新增喜愛(愛心) 按鈕
下一篇
localStorage 與 sessionStorage 介紹
系列文
打造專屬於歌手的音樂資訊網頁:從零開始的前端實作與技術分享30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言